package com.myjianzhu.zzt88.exercise.java.thread;

public class PhilosopherDemo {


    /**
     * 一. 问题描述
     * n个哲学家，n跟筷子，哲学家必须用两只筷子吃东西。他们只能使用自己左右手边的那两只筷子。做到不产生死锁以及要求高并发性。
     */
    public static void main(String[] args) {
        int philosopherCount = 10;
        Waiter waiter = new Waiter(philosopherCount);
        for (int i = 0; i < philosopherCount; i++) {
            Philosopher philosopher = new Philosopher(i, waiter);
            Thread thread = new Thread(philosopher);
            thread.start();
        }
    }

    static class Waiter {
        //筷子
        private boolean[] chopstickList;
        private int philosopherCount;

        public Waiter(int philosopherCount) {
            chopstickList = new boolean[philosopherCount];
            this.philosopherCount = philosopherCount;
            for (int i = 0; i < philosopherCount; i++) {
                chopstickList[i] = true;
            }
        }

        public synchronized void allocation(int index) throws InterruptedException {
            while (!chopstickList[index] || !chopstickList[(index + 1) % philosopherCount]) {
                System.out.println("....Philosopher---" + index + "is waiting....");
                wait();
            }
            chopstickList[index] = false;
            chopstickList[(index + 1) % philosopherCount] = false;
        }

        public synchronized void downChopsticks(int index) {
            chopstickList[index] = true;
            chopstickList[(index + 1) % philosopherCount] = true;
            notifyAll();

        }

    }

    static class Philosopher implements Runnable {
        private int index;
        private Waiter waiter;

        public Philosopher(int index, Waiter waiter) {
            this.index = index;
            this.waiter = waiter;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    waiter.allocation(index);
                    eat();
                    System.out.println("Philosopher----" + index + "begin think");
                    waiter.downChopsticks(index);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        void eat() throws InterruptedException {
            System.out.println("Philosopher ----" + index + " call the waiter...");
            System.out.println("Philosopher -----" + index + " begin to eat");
            Thread.sleep(1000);
        }
    }
}
